package org.liziyi.pss.model.cpu;

import org.liziyi.pss.common.enums.CpuStatusEnum;
import org.liziyi.pss.config.Config;
import org.liziyi.pss.entity.CpuCore;
import org.liziyi.pss.entity.ProcessControlBlock;
import org.liziyi.pss.gui.CpuGUI;

import javax.swing.*;
import java.util.concurrent.TimeUnit;

/**
 * @author liziyi
 */
public class Cpu {
    private final CpuGUI cpuGUI;
    /**
     * cpu核心
     */
    private final CpuCore[] cores;

    public Cpu(){
        cpuGUI=new CpuGUI();
        cores=new CpuCore[Config.cpuCore];
        for(int i=0;i<Config.cpuCore;i++){
            cores[i]=new CpuCore(i);
        }
    }

    /**
     * 让一个进程在cpu上运行一个时间片
     * @param pcb
     * @return
     */
    public void execTask(ProcessControlBlock pcb,CpuCore core){
        JProgressBar bar=cpuGUI.coreJprogressBarList.get(core.getCoreId());
        cpuGUI.cpuJTable.setValueAt(
                String.format(CpuStatusEnum.RUNNING.getDesc(),pcb.getPid()),core.getCoreId(),1);
        // 一个时间片内，刷新进度条的进度
        SwingUtilities.invokeLater(()->{
            bar.setMaximum(1000*pcb.getTotalTimeSlice());
            bar.setValue(1000*(pcb.getTotalTimeSlice()-pcb.getTimeSlice()));
        });
        int count=0;
        int adder=1000/(Config.timeSlice/2);
        // 2ms刷一次
        try{
            while(count<=1000){
                SwingUtilities.invokeLater(()->{
                    bar.setValue(bar.getValue()+adder);
                    cpuGUI.cpuJTable.revalidate();
                    cpuGUI.cpuJTable.repaint();
                });
                TimeUnit.MILLISECONDS.sleep(2);
                count+=adder;
            }
        }catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 当前核心恢复空闲
        SwingUtilities.invokeLater(()->bar.setValue(0));
        core.isWorking().set(false);
        cpuGUI.cpuJTable.setValueAt(
                CpuStatusEnum.FREE.getDesc(),core.getCoreId(),1);
        cpuGUI.cpuJTable.revalidate();
        cpuGUI.cpuJTable.repaint();
    }

    /**
     * 获取空闲核心
     * @return
     */
    public CpuCore getFreeCore() throws InterruptedException{
        while(true){
            for(CpuCore core:cores){
                if(core.isWorking().compareAndSet(false,true)){
                    return core;
                }
            }
            // 当前无空闲核心，稍后重试
            TimeUnit.MILLISECONDS.sleep(20);
        }
    }
    public CpuGUI getCpuGUI() {
        return cpuGUI;
    }
    public void reset(){
        for(CpuCore core:cores){
            core.isWorking().set(false);
            cpuGUI.cpuJTable.setValueAt(
                    CpuStatusEnum.FREE.getDesc(),core.getCoreId(),1);
            cpuGUI.coreJprogressBarList.get(core.getCoreId()).setValue(0);
        }
        cpuGUI.cpuJTable.revalidate();
        cpuGUI.cpuJTable.repaint();
    }
}
